From c435986318527b8dba3265d963b0e45fedb0d18b Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Sat, 26 Jun 2010 03:54:53 +0100 Subject: [PATCH] Add a babl_set_destructor Keep a callback function for each allocation instance, that allows an allocation specific callback to be called when the memory segment is freed. This makes a valgrind warning go away, most of the time no extra memory should be needed since this is likely to fit within the padding. --- babl/babl-format.c | 14 ++++++++++ babl/babl-image.c | 12 +++++++++ babl/babl-memory.c | 66 +++++++++++++--------------------------------- babl/babl-memory.h | 40 +++++++++++++++------------- 4 files changed, 65 insertions(+), 67 deletions(-) diff --git a/babl/babl-format.c b/babl/babl-format.c index 8494d9f..227dab0 100644 --- a/babl/babl-format.c +++ b/babl/babl-format.c @@ -24,6 +24,19 @@ #include "babl-internal.h" #include "babl-db.h" +static int babl_format_destruct (void *babl) +{ + BablFormat *format = babl; + if (format->image_template != NULL) + { + babl_set_destructor (format->image_template, NULL); + /* with no destructor set, the circular reference is no problem */ + babl_free (format->image_template); + format->image_template = NULL; + } + return 0; +} + static int each_babl_format_destroy (Babl *babl, void *data) @@ -75,6 +88,7 @@ format_new (const char *name, sizeof (BablType *) * (components) + sizeof (int) * (components) + sizeof (int) * (components)); + babl_set_destructor (babl, babl_format_destruct); babl->format.from_list = NULL; babl->format.component = (void *) (((char *) babl) + sizeof (BablFormat)); diff --git a/babl/babl-image.c b/babl/babl-image.c index f54c87e..ed28c89 100644 --- a/babl/babl-image.c +++ b/babl/babl-image.c @@ -22,6 +22,17 @@ #include "babl-internal.h" +static int babl_image_destruct (void *babl) +{ + BablFormat *format = BABL (babl)->image.format; + if (format && format->image_template == NULL) + { + format->image_template = babl; + return -1; /* this should avoid freeing images created for formats,. */ + } + return 0; +} + static Babl * image_new (BablFormat *format, BablModel *model, @@ -43,6 +54,7 @@ image_new (BablFormat *format, sizeof (void*) * (components) + sizeof (int) * (components) + sizeof (int) * (components)); + babl_set_destructor (babl, babl_image_destruct); babl->image.component = (void*)(((char *)babl) + sizeof (BablImage)); babl->image.sampling = (void*)(((char *)babl->image.component) + sizeof (BablComponent*) * (components)); babl->image.type = (void*)(((char *)babl->image.sampling) + sizeof (BablSampling*) * (components)); diff --git a/babl/babl-memory.c b/babl/babl-memory.c index b228447..df837a3 100644 --- a/babl/babl-memory.c +++ b/babl/babl-memory.c @@ -47,6 +47,7 @@ typedef struct { char *signature; size_t size; + int (*destructor)(void *ptr); } BablAllocInfo; #define BABL_ALIGN 16 @@ -117,6 +118,7 @@ babl_malloc (size_t size) *((void **) ret - 1) = ret - BABL_ALLOC - offset; BAI (ret)->signature = signature; BAI (ret)->size = size; + BAI (ret)->destructor = NULL; #if BABL_DEBUG_MEM babl_mutex_lock (babl_debug_mutex); mallocs++; @@ -125,6 +127,16 @@ babl_malloc (size_t size) return (void *) (ret); } +/* set a callback to be called when the segment is freed. + */ +void +babl_set_destructor (void *ptr, + int (*destructor)(void *ptr)) +{ + babl_assert (IS_BAI (ptr)); + BAI(ptr)->destructor = destructor; +} + /* Create a duplicate allocation of the same size, note * that the exact location of the allocation needs to be * passed. @@ -158,58 +170,16 @@ void babl_free (void *ptr, ...) { - /* XXX: - * Extra logic to make the bookeeping of BablImage cached - * templates work out correctly, by using a babl_image_destroy - * and custom destroy functions for babl_format this would be - * avoided and the extra overhead not needed for non image/format - * typed allocations. - */ - if (BABL_IS_BABL (ptr)) - { - switch (BABL (ptr)->instance.class_type) - { - case BABL_IMAGE: - { - BablFormat *format = BABL(ptr)->image.format; - if (format) - { - if (format->image_template == NULL) - { - format->image_template = ptr; - return; - } - else - { - } - } - } - break; - case BABL_FORMAT: - { - BablFormat *format = ptr; - if (format->image_template != NULL) - { - BAI (format->image_template)->signature = NULL; - free_f (BAI (format->image_template)); -#if BABL_DEBUG_MEM - babl_mutex_lock (babl_debug_mutex); - frees++; - babl_mutex_unlock (babl_debug_mutex); -#endif - } - format->image_template = NULL; - } - break; - default: - break; - } - } + functions_sanity (); if (!ptr) return; if (!IS_BAI (ptr)) babl_fatal ("memory not allocated by babl allocator"); - functions_sanity (); + + if (BAI (ptr)->destructor) + if (BAI (ptr)->destructor (ptr)) + return; /* bail out on non 0 return from destructor */ + BAI (ptr)->signature = NULL; free_f (BAI (ptr)); #if BABL_DEBUG_MEM diff --git a/babl/babl-memory.h b/babl/babl-memory.h index b4e0d81..251f0c3 100644 --- a/babl/babl-memory.h +++ b/babl/babl-memory.h @@ -24,24 +24,26 @@ typedef void * (* BablMallocFunc) (size_t size); typedef void (* BablFreeFunc) (void *ptr); -void babl_set_malloc (BablMallocFunc malloc_function); -void babl_set_free (BablFreeFunc free_function); -int babl_memory_sanity (void); - -void * babl_malloc (size_t size); -void babl_free (void *ptr, - ...); -void * babl_calloc (size_t nmemb, - size_t size); -void * babl_realloc (void *ptr, - size_t size); - -size_t babl_sizeof (void *ptr); -void * babl_dup (void *ptr); - -char * babl_strdup (const char *s); -char * babl_strcat (char *dest, - const char *src); - +void babl_set_malloc (BablMallocFunc malloc_function); +void babl_set_free (BablFreeFunc free_function); +int babl_memory_sanity (void); + +void * babl_malloc (size_t size); +void babl_set_destructor (void *ptr, + int (*destructor)(void *ptr)); + +void babl_free (void *ptr, + ...); +void * babl_calloc (size_t nmemb, + size_t size); +void * babl_realloc (void *ptr, + size_t size); + +size_t babl_sizeof (void *ptr); +void * babl_dup (void *ptr); + +char * babl_strdup (const char *s); +char * babl_strcat (char *dest, + const char *src); #endif -- 2.30.2